/**
 * @file camera_time_sync.c
 * @brief 摄像头时间同步功能实现
 * @version 1.0
 * @date 2023-12-05
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "camera_time_sync.h"
#include "system_utils.h"

// 内存写入数据结构
typedef struct {
    char *memory;
    size_t size;
} MemoryStruct;

size_t write_memory_callback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    MemoryStruct *mem = (MemoryStruct *)userp;
    
    char *ptr = realloc(mem->memory, mem->size + realsize + 1);
    if(!ptr) {
        log_message(LOG_LEVEL_ERROR, "摄像头时间同步: 内存分配失败");
        return 0;
    }
    
    mem->memory = ptr;
    memcpy(&(mem->memory[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;
    
    return realsize;
}

int init_curl_library(void) {
    CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
    if (code != CURLE_OK) {
        log_message(LOG_LEVEL_ERROR, "摄像头时间同步: 初始化curl库失败: %s", curl_easy_strerror(code));
        return -1;
    }
    return 0;
}

void cleanup_curl_library(void) {
    curl_global_cleanup();
}

int sync_camera_time(const CameraAuthInfo *auth_info) {
    if (!auth_info) {
        log_message(LOG_LEVEL_ERROR, "摄像头时间同步: 无效的摄像头认证信息");
        return -1;
    }
    
    CURL *curl;
    CURLcode res;
    int ret = -1;
    struct curl_slist *headers = NULL;
    
    // 使用内存缓冲区接收响应数据
    MemoryStruct response;
    response.memory = malloc(1);  // 为了realloc
    response.size = 0;    // 当前没有数据
    
    // 获取当前系统时间
    time_t now = time(NULL);
    struct tm *t = localtime(&now);
    
    // 构建XML格式的时间设置数据
    char xml_data[512];
    snprintf(xml_data, sizeof(xml_data), 
             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
             "<Time>\n"
             "  <timeMode>manual</timeMode>\n"
             "  <localTime>%04d-%02d-%02dT%02d:%02d:%02d</localTime>\n"
             "  <timeZone>CST-8:00:00</timeZone>\n"
             "</Time>",
             t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
             t->tm_hour, t->tm_min, t->tm_sec);
    
    // 初始化libcurl
    curl = curl_easy_init();
    if (!curl) {
        log_message(LOG_LEVEL_ERROR, "摄像头时间同步: 初始化CURL会话失败");
        free(response.memory);
        return -1;
    }
    
    // 构建URL
    char url[256];
    snprintf(url, sizeof(url), "http://%s/ISAPI/System/time", auth_info->ip);
    
    // 设置URL
    curl_easy_setopt(curl, CURLOPT_URL, url);
    
    // 设置用户名和密码，使用摘要认证
    curl_easy_setopt(curl, CURLOPT_USERNAME, auth_info->username);
    curl_easy_setopt(curl, CURLOPT_PASSWORD, auth_info->password);
    curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
    
    // 设置为PUT请求
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
    
    // 添加内容类型头
    headers = curl_slist_append(headers, "Content-Type: application/xml");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    
    // 设置要发送的数据
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, xml_data);
    
    // 设置回调函数接收响应数据但不打印
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_memory_callback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
    
    // 设置超时 (5秒)
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);
    
    // 执行请求
    res = curl_easy_perform(curl);
    
    // 检查请求是否成功
    if(res == CURLE_OK) {
        long response_code;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
        
        if (response_code == 200) {
            log_message(LOG_LEVEL_INFO, "成功设置摄像头 %s 的时间", auth_info->ip);
            ret = 0;
        } else {
            log_message(LOG_LEVEL_ERROR, "设置摄像头 %s 时间失败，HTTP代码: %ld", auth_info->ip, response_code);
        }
    } else {
        log_message(LOG_LEVEL_ERROR, "设置摄像头 %s 时间失败: %s", auth_info->ip, curl_easy_strerror(res));
    }
    
    // 释放header列表
    curl_slist_free_all(headers);
    
    // 清理curl
    curl_easy_cleanup(curl);
    
    // 释放响应内存
    free(response.memory);
    
    return ret;
} 